import React, { useEffect, useState } from 'react';
import _ from 'lodash';
import { nanoid } from 'nanoid';
import { arrayMoveImmutable } from 'array-move';
import { Button, Form, Input, Radio, Tabs } from 'antd';
import DraggableModal from '@/components/DraggableModal';
import DebounceWrapper from '@/components/DebounceWrapper';
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
import { HolderOutlined, MinusCircleOutlined, SettingOutlined } from '@ant-design/icons';
import styles from './index.less';

const { Group } = Radio;
const layout = {
  labelCol: { span: 5 },
  wrapperCol: { span: 17 },
};
const DebounceButton = DebounceWrapper(Button);
const SortableIcon = SortableHandle(HolderOutlined);
const SortableListItem = SortableElement((props) => (
  <div {...props} className={styles.rowListItem} />
));
const SortableListContainer = SortableContainer((props) => (
  <div {...props} className={styles.rowListContainer} />
));

const SelectControl = ({ value: valueInfo, onChange }) => {
  const { asyncDictType, options } = valueInfo || {};

  return (
    <div className={styles.searchControlAttribute}>
      <div className={styles.searchControlAttributeTitle}>规则项：</div>
      <Tabs size="small">
        <Tabs.TabPane key="asyncDictType" tab="从字典获取">
          <div className={styles.searchControlAttributeDict}>
            <span>字典code:</span>
            <Input
              size="small"
              value={asyncDictType || ''}
              placeholder="输入字典code"
              onChange={(e) => {
                onChange({
                  ...(valueInfo || {}),
                  asyncDictType: e.target.value,
                });
              }}
            />
          </div>
        </Tabs.TabPane>
        <Tabs.TabPane key="filterOptions" tab="配置筛选规则">
          <div className={styles.searchControlAttributeOptions}>
            <div className={styles.searchControlAttributeOptionsTitle}>
              <span>选项名</span>
              <span>选项值</span>
            </div>
            {(options || []).map(({ label, value, id }) => (
              <div key={id} className={styles.searchControlAttributeOptionsList}>
                <Input
                  size="small"
                  value={label}
                  bordered={false}
                  onChange={(e) => {
                    const nextOptions = [...(options || [])];
                    const index = _.findIndex(nextOptions, ({ id: currentId }) => currentId === id);
                    if (index > -1) {
                      nextOptions[index].label = e.target.value;
                    }
                    onChange({
                      ...(valueInfo || {}),
                      options: nextOptions,
                    });
                  }}
                />
                <Input
                  size="small"
                  value={value}
                  bordered={false}
                  onChange={(e) => {
                    const nextOptions = [...(options || [])];
                    const index = _.findIndex(nextOptions, ({ id: currentId }) => currentId === id);
                    if (index > -1) {
                      nextOptions[index].value = e.target.value;
                    }
                    onChange({
                      ...(valueInfo || {}),
                      options: nextOptions,
                    });
                  }}
                />
              </div>
            ))}
            <DebounceButton
              size="small"
              type="dashed"
              onClick={() => {
                const nextOptions = [...(options || []), { id: nanoid(12) }];
                onChange({
                  ...(valueInfo || {}),
                  options: nextOptions,
                });
              }}
            >
              添加选项
            </DebounceButton>
          </div>
        </Tabs.TabPane>
      </Tabs>
    </div>
  );
};

const SortableSearch = ({ search, setProp, openModal }) => {
  return (
    <SortableListContainer
      useDragHandle
      disableAutoscroll
      helperClass="common-table-column-dragging"
      onSortEnd={({ oldIndex, newIndex }) => {
        if (oldIndex !== newIndex) {
          setProp((props) => {
            const nextColumns = arrayMoveImmutable(props.search.slice(), oldIndex, newIndex).filter(
              (item) => !!item,
            );
            props.search = nextColumns;
          }, 500);
        }
      }}
    >
      {(search || []).map(({ id, key, props, ...restProps }, index) => (
        <SortableListItem key={id} index={index} title={props?.label || ''}>
          <div className={styles.searchControlItem}>
            <SortableIcon />
            <div className={styles.searchControlItemInput}>
              <Input
                size="small"
                value={props?.label || ''}
                bordered={false}
                onChange={(e) => {
                  setProp((props) => {
                    const nextSearch = [...props.search];
                    const index = _.findIndex(nextSearch, ({ id: currentId }) => currentId === id);
                    if (index > -1) {
                      if (_.isPlainObject(nextSearch[index].props)) {
                        nextSearch[index].props.label = e.target.value;
                      } else {
                        nextSearch[index].props = { label: e.target.value };
                      }
                      props.search = nextSearch;
                    }
                  }, 500);
                }}
              />
            </div>
            <div className={styles.searchControlItemInput}>
              <Input
                size="small"
                value={key}
                bordered={false}
                onChange={(e) => {
                  setProp((props) => {
                    const nextSearch = [...props.search];
                    const index = _.findIndex(nextSearch, ({ id: currentId }) => currentId === id);
                    if (index > -1) {
                      nextSearch[index].key = e.target.value;
                      props.search = nextSearch;
                    }
                  }, 500);
                }}
              />
            </div>
            <div className={styles.searchControlItemActions}>
              <SettingOutlined
                onClick={() => {
                  openModal({ id, key, props, ...restProps });
                }}
              />
              <MinusCircleOutlined
                onClick={() => {
                  setProp((props) => {
                    const nextSearch = [...props.search];
                    const index = _.findIndex(nextSearch, ({ id: currentId }) => currentId === id);
                    if (index > -1) {
                      nextSearch.splice(index, 1);
                      props.search = nextSearch;
                    }
                  }, 500);
                }}
              />
            </div>
          </div>
        </SortableListItem>
      ))}
    </SortableListContainer>
  );
};

const SearchSettingModal = ({ visible, options, setProp, closeModal }) => {
  const [form] = Form.useForm();
  const [currentSearchType, setCurrentSearchType] = useState(undefined);

  useEffect(() => {
    if (visible) {
      if (!_.isEmpty(options)) {
        const defaultFormValue = {
          key: options.key || '',
          label: options.props?.label || '',
          searchType: options.searchType || undefined,
          selectConfig: {
            asyncDictType: options.componentProps?.asyncOptions?.asyncDictType || '',
            options: options.componentProps?.options || [],
          },
          placeholder: options.componentProps?.placeholder || '',
        };
        setCurrentSearchType(options.searchType);
        form.setFieldsValue(defaultFormValue);
      }
    } else {
      form.resetFields();
      setCurrentSearchType(undefined);
    }
  }, [visible]);

  const handleConfirm = () => {
    form.validateFields().then((values) => {
      setProp((props) => {
        const nextSearch = [...(props.search || [])];

        const selectComponentProps =
          values.searchType === 'IN'
            ? _.assign(
                {},
                values.selectConfig?.asyncDictType
                  ? { asyncOptions: { asyncDictType: values.selectConfig?.asyncDictType } }
                  : { options: values.selectConfig?.options || [] },
              )
            : {};

        const nextSearchItem = {
          key: values.key,
          Component: values.searchType === 'LIKE' ? 'Input' : 'Select',
          searchType: values.searchType,
          props: {
            label: values.label || '',
            initialValue: values.searchType === 'LIKE' ? '' : undefined,
          },
          componentProps: {
            placeholder: values.placeholder || '',
            ...selectComponentProps,
          },
        };

        if (options.id) {
          const index = _.findIndex(nextSearch, ({ id: currentId }) => currentId === options.id);
          if (index > -1) {
            nextSearch[index] = _.assign({}, nextSearchItem, { id: options.id });
            props.search = nextSearch;
          }
        } else {
          nextSearch.push(_.assign({}, nextSearchItem, { id: nanoid(12) }));
          props.search = nextSearch;
        }
      }, 500);
      closeModal();
    });
  };

  return (
    <DraggableModal
      title={`${options.id ? '编辑' : '新增'}搜索项`}
      visible={visible}
      onCancel={closeModal}
      footer={[
        <DebounceButton key="cancel" onClick={closeModal}>
          取消
        </DebounceButton>,
        <DebounceButton key="confirm" type="primary" onClick={handleConfirm}>
          确定
        </DebounceButton>,
      ]}
    >
      <Form {...layout} form={form} name="pro-table-search-attribute">
        <Form.Item name="label" label="操作描述" initialValue="">
          <Input placeholder="请输入操作描述" />
        </Form.Item>
        <Form.Item name="key" label="操作Code" initialValue="">
          <Input placeholder="请输入操作Code" />
        </Form.Item>
        <Form.Item
          name="searchType"
          label="操作类型"
          initialValue={undefined}
          rules={[{ required: true, message: '请选择操作类型' }]}
        >
          <Group
            onChange={(e) => {
              setCurrentSearchType(e.target.value || '');
            }}
          >
            <Radio value="LIKE">关键字搜索</Radio>
            <Radio value="IN">筛选</Radio>
          </Group>
        </Form.Item>
        {currentSearchType === 'IN' && (
          <Form.Item name="selectConfig" label="筛选项" initialValue={{}}>
            <SelectControl />
          </Form.Item>
        )}
        <Form.Item name="placeholder" label="占位描述" initialValue="">
          <Input placeholder="请输入占位描述" />
        </Form.Item>
      </Form>
    </DraggableModal>
  );
};

export default ({ search, setProp }) => {
  const [modalVisible, setModalVisible] = useState(false);
  const [modalOptions, setModalOptions] = useState({});

  const handleOpenModal = (opts) => {
    setModalOptions(opts);
    setModalVisible(true);
  };

  const closeModal = () => {
    setModalVisible(false);
    setModalOptions({});
  };

  return (
    <>
      <div className={styles.searchControl}>
        <div>搜索项：</div>
        <div className={styles.searchControlList}>
          <div className={styles.searchControlListTitle}>
            <span>操作描述</span>
            <span>code</span>
            <span>操作</span>
          </div>
          <SortableSearch search={search} setProp={setProp} openModal={handleOpenModal} />
          <DebounceButton
            size="small"
            type="dashed"
            onClick={() => {
              setModalVisible(true);
            }}
          >
            添加搜索项
          </DebounceButton>
        </div>
      </div>

      <SearchSettingModal
        visible={modalVisible}
        options={modalOptions}
        setProp={setProp}
        closeModal={closeModal}
      />
    </>
  );
};
